/*
 * 插件支持的配置信息(基于不同的配置信息，实现不同的功能)： 
 *    + title[string] 标题
 *    + template[string] 自定义的内容或者模板(基于ES6的模板字符串,拼接更丰富的内容结构)
 *    + buttons[array] 自定义按钮(组)
 *      [{text:'确定',click:[callback]},...]
 *    + modal[boolean] 控制遮罩层是否显示 默认是true
 *    + drag[boolean] 是否允许拖拽 默认是true
 *    + onopen[function] 打开
 *    + onclose[function] 关闭
 * 拖拽的生命周期函数「当前操作的某个节点上，允许用户自定义处理的事情」
 *   「发布订阅」
 *    + 拖拽开始 ondragstart
 *    + 拖拽中 ondraging
 *    + 拖拽结束 ondragend
 * 
 * // 发布订阅
 *  // 工具库
 */

import utils from './lib/utils'; 
import Sub from './lib/sub';


// 插件的核心
function ModalPlugin(config){

  let self = this;
  self.config = config;
  self.$drag_modal = null;
  self.$drag_content = null;

  self.startX = 0;
  self.startY = 0;

  self.startL = 0;
  self.startT = 0;

  self._MOVE = null;
  self._UP = null;

  self.init();
}

ModalPlugin.prototype = {
    version:'1.0.0',
    constructor:ModalPlugin,
    init(){
        let self = this;
        self.create();

        // 基于事件委托实现 容器中元素点击处理的相关事务 关闭按钮 && 自定义按钮
        if(self.$drag_content){
            self.$drag_content.addEventListener('click',function(ev){
                let target = ev.target,
                    targetTag = target.tagName,
                    targetClass = target.className;
                // 关闭按钮
                if(targetTag === 'A' && targetClass === 'drag_close') {
                    self.close();
                    return ;
                }
                
                // 自定义按钮
                if(targetTag === 'A' && targetClass === 'drag_button') {
                    let index = +target.getAttribute('index'),
                        item = self.config.buttons[index];
                        // 判断 不为空 并且 是函数 就执行函数
                     if(item && utils.isFunction(item.click)){
                        item.click.call(self,self);
                     }
                    return ;
                }

            })
        }

        if(self.config.drag){
            // 开启拖拽
            let $drag_head = self.$drag_content.querySelector('.drag_head');
                $drag_head.style.cursor = 'move'; 
                $drag_head.addEventListener('mousedown',self.down.bind(self));
        }
 
    },
    // 动态创建结构
    create(){
        let self = this,
        config = self.config,
        fragment = document.createDocumentFragment(); 
        // 创建遮罩层
        if(config.modal){
            self.$drag_modal = document.createElement('div');
            self.$drag_modal.className = 'drag_modal';
            fragment.appendChild(self.$drag_modal);
        }

        // 创建内容
        self.$drag_content = document.createElement('div');
        self.$drag_content.className = 'drag_content'; 
        self.$drag_content.innerHTML = `
                <div class="drag_head">
                ${config.title}
                <a href="javascript:;" class="drag_close"></a>
            </div>
            <div class="drag_main">${config.template} </div>
                ${config.buttons.length > 0 ? 
                    ` <div class="drag_foot"> 
                        ${config.buttons.map((item,index) => {
                            return  `<a href="javascript:;" class="drag_button" index="${index}">${item.text}</a>`
                        }).join('')} 
                    </div> ` 
                 : ``} 
            `;

        fragment.appendChild(self.$drag_content);
        // 把动态元素添加到页面当中
        document.body.appendChild(fragment);
        fragment = null;

        // 控制元素显示
        self.$drag_content.offsetHeight; // 刷新渲染队列
        self.$drag_modal ?   self.$drag_modal.style.opacity = 1 : null;
        self.$drag_content ? self.$drag_content.style.opacity = 1 : null;

        // 改变盒子居中的方式
        let HTML = document.documentElement;
        self.$drag_content.style.left = `${(HTML.clientWidth - self.$drag_content.clientWidth)/2}px`;
        self.$drag_content.style.top = `${(HTML.clientHeight - self.$drag_content.clientHeight)/2}px`;
        self.$drag_content.style.transform = 'translate(0,0)';
    },
    // 关闭弹窗
    close(){
        let self = this,
            body = document.body; 
        if(self.$drag_modal){
            self.$drag_modal.style.opacity = 0;
            // 动画结束之后移除元素
            self.$drag_modal.ontransitionend = () => {
                body.removeChild(self.$drag_modal);
                self.$drag_modal.ontransitionend = null;
            }
        }

        if(self.$drag_content){
            self.$drag_content.style.opacity = 0;
            // 动画结束之后移除元素
            self.$drag_content.ontransitionend = () => {
                body.removeChild(self.$drag_content);
                self.$drag_content.ontransitionend = null;
            }
        }
    },
    // 拖拽系列方法
    down(ev){
        let self = this;

        self.startX = ev.pageX;
        self.startY = ev.pageY;
 
        self.startL = self.$drag_content.offsetLeft;
        self.startT = self.$drag_content.offsetTop;
 
        self._MOVE = self.move.bind(self);
        self._UP = self.up.bind(self);
        document.addEventListener('mousemove',self._MOVE); 
        document.addEventListener('mouseup',self._UP); 
    },
    move(ev){
        let self = this,
            curL = ev.pageX - self.startX + self.startL,
            curT = ev.pageY - self.startY + self.startT;

            // 边界判断
            let HTML = document.documentElement,
                minL = 0,
                minT = 0,
                maxL = HTML.clientWidth - self.$drag_content.offsetWidth,
                maxT = HTML.clientHeight - self.$drag_content.offsetHeight; 

            curL = curL < minL ? minL : (curL > maxL ? maxL : curL);
            curT = curT < minT ? minT : (curT > maxT ? maxT : curT);

            self.$drag_content.style.left = `${curL}px`;
            self.$drag_content.style.top = `${curT}px`; 
    },
    up(){
        let self = this;
        document.removeEventListener('mousemove',self._MOVE); 
        document.removeEventListener('mouseup',self._UP); 
    }
}
 
// 暴露的API 
// 定义每一个参数规则
const props = {
    title:{
        type:'string',
        default:"系统温馨提示"
    },
    template:{
        type:'string',
        required: true 
    },
    buttons:{
        type:'array',
        default:[]
    },
    modal:{
        type:'boolean',
        default:true
    },
    drag:{
        type:'boolean',
        default:true
    },
    drag:{
        type:'boolean',
        default:true
    },
    onopen:{
        type:'function',
        default:()=>{}
    },
    onclose:{
        type:'function',
        default:()=>{}
    },
}

const proxyModal = function proxyModal(options){
    // 验证配置项
    !options || !utils.isPlainObject(options) ? options = {} : null;

    // console.log(options);
    let config = {};
    utils.each(props,(key,rule)=>{
        let opValue = options[key],
            {type,default:defaultValue,required} = rule; 
        // options 没有传递配置项 : 验证是否为必传 && 取参数默认值
        if(typeof opValue === 'undefined'){
            if(required) throw new TypeError(`${key} must be required`);
            config[key] = defaultValue
            return ;
        }
        //  options 有传递 key 这一项, 验证值的格式 && 取传进来的值
        if(utils.toType(opValue) !== type ) throw new TypeError(`${key} must be an ${type}`);
        // 对象合并
        config[key] =  utils.merge(defaultValue,opValue); 
    });
    
    return new ModalPlugin(config);
};

if(typeof window !== "undefined"){
    window.M = window.ModalPlugin = proxyModal;
}

if(typeof module === "object" && typeof module.exports === 'object') {
    module.exports = proxyModal;
}
   